#include "stdafx.h"
#include "ImmData.h"
#include "ImmStuff.h"

BOOL ImmData::IMM_CompStartSend = 0;

ImmData::ImmData(HIMC hIMC)
{
	this->hIMC = hIMC;
	this->lpIMC = NULL;
	this->lpCompStr = NULL;
	this->lpCandInfo = NULL;
	this->lockOK = this->_lockIMM();
	if(this->lockOK)
	{
		this->lpCompStrClass = new CompositionStringClass(this->lpCompStr);
		this->lpCandStrClass = new CandidateStringClass(this->lpCandInfo);		
	}
}

ImmData::~ImmData()
{
	if(this->lockOK)
	{
		this->_unLockIMM();
		delete this->lpCompStrClass;
		delete this->lpCandStrClass;
	}
}

BOOL ImmData::_lockIMM()
{
	if(!this->hIMC)
		return FALSE;
	if (!(this->lpIMC = ImmLockIMC(this->hIMC)))
		return FALSE;
	if(!(this->lpCompStr = (LPCOMPOSITIONSTRING)ImmLockIMCC(this->lpIMC->hCompStr)))
		return FALSE;

	if(!(this->lpCandInfo = (LPCANDIDATEINFO)ImmLockIMCC(this->lpIMC->hCandInfo)))	
		return FALSE;

	return TRUE;
}

BOOL ImmData::LockImmOK() const
{
	return this->lockOK;
}
VOID ImmData::_unLockIMM()
{
	ImmUnlockIMCC(lpIMC->hCompStr);
	ImmUnlockIMCC(lpIMC->hCandInfo);
	ImmUnlockIMC(hIMC);
}

BOOL ImmData::IsIMEMessage(UINT message)
{
	switch(message)
	{
	case WM_IME_STARTCOMPOSITION:
	case WM_IME_ENDCOMPOSITION:
	case WM_IME_COMPOSITION:
	case WM_IME_NOTIFY:
	case WM_IME_SETCONTEXT:
	case WM_IME_CONTROL:
	case WM_IME_COMPOSITIONFULL:
	case WM_IME_SELECT:
	case WM_IME_CHAR:
		return TRUE;
	}
	return FALSE;
}

BOOL ImmData::MakeResultString(LPDWORD lpdwTransKey,BOOL fFlag)
{
	GENEMSG GnMsg;
	LPMYCOMPSTR lpMyComp = (LPMYCOMPSTR)lpCompStr;

	if(!fFlag){
		this->lpCompStrClass->SetResultString(_T("\0"));
	}
	this->lpCompStrClass->ClearCompStr();
	this->lpCandStrClass->ClearCandidateStr();

	if(!IMM_CompStartSend)
		this->WM_StartComp(lpdwTransKey);
	this->WM_CompStr(lpdwTransKey);
	this->WM_SetStatusOpen(lpdwTransKey);
	this->WM_CompResult(lpdwTransKey);
	this->WM_EndComp(lpdwTransKey);

	return TRUE;
}

VOID ImmData::OutputCompString(LPDWORD lpdwTransKey)
{
	this->lpCompStrClass->OutputCompString();
	this->MakeResultString(lpdwTransKey,TRUE);
}

BOOL ImmData::GenerateMessage(LPDWORD lpdwTransKey,LPGENEMSG lpGeneMsg)
{
	if (lpdwTransKey){
		return GenerateMessageToTransKey(lpdwTransKey,lpGeneMsg);
	}
	if (IsWindow(this->lpIMC->hWnd))
	{
		LPDWORD lpdw;
		if (!(this->lpIMC->hMsgBuf = ImmReSizeIMCC(this->lpIMC->hMsgBuf,sizeof(DWORD) * (lpIMC->dwNumMsgBuf +1) * 3)))
			return FALSE;

		if (!(lpdw = (LPDWORD)ImmLockIMCC(this->lpIMC->hMsgBuf)))
			return FALSE;

		lpdw += (this->lpIMC->dwNumMsgBuf) * 3;
		*((LPGENEMSG)lpdw) = *lpGeneMsg;
		ImmUnlockIMCC(this->lpIMC->hMsgBuf);
		this->lpIMC->dwNumMsgBuf++;

		ImmGenerateMessage(this->hIMC);
	}
	return TRUE;
}

BOOL ImmData::GenerateMessageToTransKey(LPDWORD lpdwTransKey,LPGENEMSG lpGeneMsg) CONST
{
	LPDWORD lpdwTemp;
	ImmStuff::uNumTransKey++;
	if (ImmStuff::uNumTransKey >= (UINT)*lpdwTransKey)
	{       
		return FALSE;
	}

	lpdwTemp = (LPDWORD)lpdwTransKey + 1 + (ImmStuff::uNumTransKey - 1)*3;
	*(lpdwTemp++) = lpGeneMsg->msg;
	*(lpdwTemp++) = lpGeneMsg->wParam;
	*(lpdwTemp++) = lpGeneMsg->lParam;
	return TRUE;
}

BOOL ImmData::IsCompStr() CONST
{
	if(!this->lockOK)
		return FALSE;

	if (ImmGetIMCCSize(this->lpIMC->hCompStr) < sizeof (COMPOSITIONSTRING))
	{
		return FALSE;
	}
	return (this->lpCompStr->dwCompStrLen > 0);
}

VOID ImmData::WM_EndComp(LPDWORD lpdwTransKey)
{
	GENEMSG GnMsg;
	GnMsg.msg = WM_IME_ENDCOMPOSITION;
	GnMsg.wParam = 0;
	GnMsg.lParam = 0;
	GenerateMessage(lpdwTransKey,&GnMsg);
	IMM_CompStartSend = FALSE;
}
VOID ImmData::WM_StartComp(LPDWORD lpdwTransKey)
{
	if(IMM_CompStartSend)
		//this->WM_EndComp(lpdwTransKey);
		return;
	GENEMSG GnMsg;
	GnMsg.msg = WM_IME_STARTCOMPOSITION;
	GnMsg.wParam = 0;
	GnMsg.lParam = 0;
	GenerateMessage(lpdwTransKey,&GnMsg);
	IMM_CompStartSend = TRUE;
}
VOID ImmData::WM_CompStr(LPDWORD lpdwTransKey)
{
	GENEMSG GnMsg;
	GnMsg.msg = WM_IME_COMPOSITION;
	GnMsg.wParam = 0;
	GnMsg.lParam = GCS_COMPSTR;
	GenerateMessage(lpdwTransKey,&GnMsg);
}
VOID ImmData::WM_CompResult(LPDWORD lpdwTransKey)
{
	GENEMSG GnMsg;
	GnMsg.msg = WM_IME_COMPOSITION;
	GnMsg.wParam = 0;
	GnMsg.lParam = GCS_RESULTSTR;
	GenerateMessage(lpdwTransKey,&GnMsg);
}
VOID ImmData::WM_OpenStatus(LPDWORD lpdwTransKey)
{
	GENEMSG GnMsg;
	GnMsg.msg = WM_IME_NOTIFY;
	GnMsg.wParam = IMN_OPENSTATUSWINDOW;
	GnMsg.lParam = 0;
	GenerateMessage(lpdwTransKey,(LPGENEMSG)&GnMsg);
}
VOID ImmData::WM_SetStatusOpen(LPDWORD lpdwTransKey)
{
	GENEMSG GnMsg;
	GnMsg.msg = WM_IME_NOTIFY;
	GnMsg.wParam = IMN_SETOPENSTATUS;
	GnMsg.lParam = 0;
	GenerateMessage(lpdwTransKey,(LPGENEMSG)&GnMsg);
}
VOID ImmData::SendTextToApp(LPDWORD lpdwTransKey,CONST LPTSTR pText)
{
	this->lpCompStrClass->SetCompositionString(pText);
	MakeResultString(lpdwTransKey,TRUE);
}
CompositionStringClass* ImmData::GetCompStrClass()
{
	return this->lpCompStrClass;
}
CandidateStringClass* ImmData::GetCandStrClass()
{
	return this->lpCandStrClass;
}

VOID ImmData::SetImmOpen(BOOL state)
{
	if(this->lockOK)
	{
		this->lpIMC->fOpen = state;
	}
}
BOOL ImmData::GetImmOpenState() CONST
{
	if(this->lockOK)
		return this->lpIMC->fOpen;
	else
		return FALSE;
}
VOID ImmData::ToggleImmOpenState()
{
	if(this->lockOK)
		this->lpIMC->fOpen = !this->lpIMC->fOpen;

}
VOID ImmData::Initial()
{
	if(this->lockOK)
	{
		ImmUnlockIMCC(lpIMC->hCompStr);
		ImmUnlockIMCC(lpIMC->hCandInfo);
		delete this->lpCandStrClass;
		delete this->lpCompStrClass;
	}

	this->SetImmOpen(TRUE);
	this->lpIMC->hCompStr = ImmReSizeIMCC(this->lpIMC->hCompStr,sizeof(MYCOMPSTR));
	if (this->lpCompStr = (LPCOMPOSITIONSTRING)ImmLockIMCC(this->lpIMC->hCompStr)) 
	{
		this->lpCompStrClass = new CompositionStringClass(this->lpCompStr);
		this->lpCompStrClass->Initial();
	}
	this->lpIMC->hCandInfo = ImmReSizeIMCC(this->lpIMC->hCandInfo,sizeof(MYCAND));
	if (this->lpCandInfo = (LPCANDIDATEINFO)ImmLockIMCC(this->lpIMC->hCandInfo)) 
	{
		this->lpCandStrClass = new CandidateStringClass(this->lpCandInfo);
		this->lpCandStrClass->Initial();
	}
}